package com.jlpay.open.jlpay.sdk.java.common.crypto;

import com.jlpay.open.jlpay.sdk.java.common.crypto.annotation.DataCrypto;
import com.jlpay.open.jlpay.sdk.java.common.crypto.annotation.Decrypt;
import com.jlpay.open.jlpay.sdk.java.common.crypto.annotation.Encrypt;
import com.jlpay.open.jlpay.sdk.java.common.crypto.model.AnnotationData;
import com.jlpay.open.jlpay.sdk.java.utils.AnnotationUtils;
import com.jlpay.open.jlpay.sdk.java.utils.CollectionUtils;
import com.jlpay.open.jlpay.sdk.java.utils.ReflectionUtils;
import com.jlpay.open.jlpay.sdk.java.utils.StringUtils;
import com.jlpay.open.jlpay.sdk.java.utils.gm.keyentity.Sm2KeyEntity;
import com.jlpay.open.jlpay.sdk.java.utils.gm.keyentity.Sm4KeyEntity;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @author chenjunhong
 * @date 2024/4/10
 */
public class CryptoHelper {
    public static String encryptWithSm4(String plaintext, String key) {
        Sm4KeyEntity sm4KeyEntity = new Sm4KeyEntity();
        sm4KeyEntity.initKey(key);
        return sm4KeyEntity.encrypt(plaintext);
    }

    public static String decryptWithSm4(String cipherText, String key) {
        Sm4KeyEntity sm4KeyEntity = new Sm4KeyEntity();
        sm4KeyEntity.initKey(key);
        return sm4KeyEntity.decrypt(cipherText);
    }

    public static void encryptWithSm4(Object body, String key) {
        if (!requireEncrypt(body)) {
            return;
        }
        List<AnnotationData> decryptFields = AnnotationUtils.getAllAnnotationData(body, Encrypt.class);
        if (CollectionUtils.isEmpty(decryptFields)) {
            return;
        }
        Sm4KeyEntity sm4KeyEntity = new Sm4KeyEntity();
        sm4KeyEntity.initKey(key);
        for (AnnotationData annotationData : decryptFields) {
            Field field = annotationData.getField();
            String plaintext = (String)annotationData.getOldValue();
            String cipherText = null;
            if (StringUtils.isNotBlank(plaintext)) {
                cipherText = sm4KeyEntity.encrypt(plaintext);
            }
            ReflectionUtils.setField(field, annotationData.getObj(), cipherText);
        }
    }

    public static void decryptWithSm4(Object body, String key) {
        if (!requireDecrypt(body)) {
            return;
        }
        List<AnnotationData> decryptFields = AnnotationUtils.getAllAnnotationData(body, Decrypt.class);
        if (CollectionUtils.isEmpty(decryptFields)) {
            return;
        }
        Sm4KeyEntity sm4KeyEntity = new Sm4KeyEntity();
        sm4KeyEntity.initKey(key);
        for (AnnotationData annotationData : decryptFields) {
            Field field = annotationData.getField();
            String cipherText = (String)annotationData.getOldValue();
            String plainText = null;
            if (StringUtils.isNotBlank(cipherText)) {
                plainText = sm4KeyEntity.decrypt(cipherText);
            }
            ReflectionUtils.setField(field, annotationData.getObj(), plainText);
        }
    }

    public static boolean requireEncrypt(Object body) {
        DataCrypto annotation = body.getClass().getAnnotation(DataCrypto.class);
        return annotation != null && annotation.encrypt();
    }

    public static boolean requireDecrypt(Object body) {
        DataCrypto annotation = body.getClass().getAnnotation(DataCrypto.class);
        return annotation != null && annotation.decrypt();
    }

    public static String encryptWithSm2(String plaintext, String pubKey) {
        Sm2KeyEntity sm2KeyEntity = new Sm2KeyEntity();
        sm2KeyEntity.initPubKey(pubKey);
        return sm2KeyEntity.encrypt(plaintext);
    }

    public static String decryptWithSm2(String cipherText, String priKey) {
        Sm2KeyEntity sm2KeyEntity = new Sm2KeyEntity();
        sm2KeyEntity.initPriKey(priKey);
        return sm2KeyEntity.decrypt(cipherText);
    }
}
